package com.zpark.config;

import com.zpark.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

/**
 * Security配置类
 */
@Configuration
public class SecurityConfig {

//    @Autowired
//    private MyUserDetailsService userDetailsService;

    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置并构建AuthenticationManager，用于处理应用程序的认证需求。
     * 这个方法通过利用HttpSecurity的对象来配置AuthenticationManagerBuilder，从而定制用户详情服务和密码编码器。
     *
     * @param http Security配置的HttpSecurity对象，用于访问和配置HTTP安全相关的设置。
     * @param bCryptPasswordEncoder 用于加密和验证用户密码的BCryptPasswordEncoder实例。
     * @param userDetailService 自定义的用户详情服务，用于从数据库或其他源加载用户详情。
     * @return 返回构建完成的AuthenticationManager实例，用于处理认证请求。
     * @throws Exception 如果配置过程中出现错误，将抛出异常。
     */
    //@Bean
    /*public AuthenticationManager authenticationManager(HttpSecurity http,
                                      BCryptPasswordEncoder bCryptPasswordEncoder,
                                      MyUserDetailsService userDetailService) throws Exception {

        // 从HttpSecurity对象中获取AuthenticationManagerBuilder的实例
        // 通过AuthenticationManagerBuilder来配置用户详情服务和密码编码器
        return http.getSharedObject(AuthenticationManagerBuilder.class)
                .userDetailsService(userDetailService) // 设置自定义的用户详情服务
                .passwordEncoder(bCryptPasswordEncoder) // 设置密码编码器为BCryptPasswordEncoder
                .and() // 确认配置并构建AuthenticationManager
                .build();
    }*/


    /**
     * 配置一个内存中的用户详情服务，用于Spring Security。
     * 这个方法通过创建两个用户账号并设置其密码和角色，来初始化用户的认证信息。
     * 使用BCryptPasswordEncoder对用户密码进行加密，增强安全性。
     *
     * @param passwordEncoder 用于加密用户密码的BCryptPasswordEncoder实例。
     * @return 返回初始化后的InMemoryUserDetailsManager实例，其中包含两个预定义的用户账号。
     */
    @Bean
    public UserDetailsService userDetailsService(BCryptPasswordEncoder passwordEncoder) {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        // 创建一个用户名为"user"，密码为"123456"，角色为"USER"的用户
        manager.createUser(User.withUsername("user")
                .password(passwordEncoder.encode("123456"))
                .roles("USER")
                .build());

        // 创建一个用户名为"admin"，密码为"123456"，角色为"USER"和"ADMIN"的用户
        manager.createUser(User.withUsername("admin")
                .password(passwordEncoder.encode("789789"))
                .roles("USER", "ADMIN")
                .build());

        return manager;
    }

    // 非常重要的方法，负责编写拦截规则（就是哪些资源需要验证）
    /**
     * 配置安全过滤链。
     * 该方法定义了应用程序的不同URL路径的访问权限（基于web的权限校验），以及启用或禁用的各种安全特性。
     *
     * @param http 用于配置安全性的对象，通过调用其方法来设置各种安全策略。
     * @return 返回配置后的SecurityFilterChain对象，用于Spring Security的过滤链。
     * @throws Exception 如果配置过程中出现错误，可能会抛出异常。
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // 禁用CSRF（跨站请求伪造）保护。
        http.csrf()
                .disable()
                // 配置请求授权规则。
                .authorizeRequests()
                // 设置DELETE方法请求需要ADMIN角色。
                .antMatchers(HttpMethod.DELETE)
                .hasRole("ADMIN")
                // 设置以/admin/开头的路径需要ADMIN角色。
                .antMatchers("/admin/**")
                .hasAnyRole("ADMIN")
                // 设置以/user/开头的路径需要USER或ADMIN角色。
                .antMatchers("/user/**")
                .hasAnyRole("USER", "ADMIN")
                // 设置以/login/开头的路径允许匿名访问。
                .antMatchers("/login/**")
                .anonymous()
                // 任何其他请求都需要身份验证。
                .anyRequest()
                .authenticated()
                // 启用HTTP基本身份验证。
                .and()
                .httpBasic()
                // 配置会话管理，设置为无状态，意味着不创建会话。
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 返回构建后的HttpSecurity配置。
        return http.build();
    }



}
